package com.ch8.demo02;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author woldier
 * @version 1.0
 * @description 自定义AQS独占锁
 * @date 2023/6/7 9:03
 **/
public class TestAQS implements Lock {

    private final Sync sync;

    public TestAQS() {
        this.sync = new Sync();
    }

    /**
     * 自定义的同步类 需要实现AbstractQueuedSynchronizer 的五个方法
     */
     static class Sync extends AbstractQueuedSynchronizer {



        /***
         *
         * description 尝试获取
         *
         * @param arg  设置的状态
         * @return boolean
         * @author: woldier
         * @date: 2023/6/7 9:31
         */
        @Override
        protected boolean tryAcquire(int arg) {
            /*如果获取锁成功,那么设置当前线程为拥有者线程*/
            if (compareAndSetState(0, arg)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;

        }

        /**
         * 释放锁
         *
         * @param arg the release argument. This value is always the one
         *            passed to a release method, or the current state value upon
         *            entry to a condition wait.  The value is otherwise
         *            uninterpreted and can represent anything you like.
         * @return
         */
        @Override
        protected boolean tryRelease(int arg) {
            /*释放锁需要修改state与ExclusiveOwnerThread成员变量*/
            /*state 关键字有volatile修饰而ExclusiveOwnerThread没有,根据写前读后,应该先修改ExclusiveOwnerThread,再修改state 防止指令重排,使得其结果对所有线程可见*/
            setExclusiveOwnerThread(null);
            this.setState(0);
            return true;
        }


        /***
         *
         * description 是否持有独占锁
         *
         *
         * @return boolean
         * @author: woldier
         * @date: 2023/6/7 9:38
         */
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }


        /***
         *
         * description 获取新的条件变量
         *
         *
         * @return java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject
         * @author: woldier
         * @date: 2023/6/7 9:06
         */
        final ConditionObject newCondition() {
            return new ConditionObject();
        }


        /***
         *
         * description 查看是否已经是上锁状态
         *
         *
         * @return boolean
         * @author: woldier
         * @date: 2023/6/7 9:07
         */
        final boolean isLocked() {
            return getState() != 0;
        }
    }

    //-----------------------------------Lock interface implement  start------------------------------------//

    /**
     * 加锁
     */
    @Override
    public void lock() {
        sync.acquire(1);
    }

    /***
     *
     * description 加锁,可打断
     *
     *
     * @return void
     * @author: woldier
     * @date: 2023/6/7 9:12
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /***
     *
     * description 尝试获取锁(一次)
     *
     *
     * @return boolean
     * @author: woldier
     * @date: 2023/6/7 9:12
     */
    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    /***
     *
     * description 尝试加锁,带超时时间
     *
     * @param time 时间
     * @param unit   时间单位
     * @return boolean
     * @author: woldier
     * @date: 2023/6/7 9:12
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1,unit.toNanos(time));
    }

    /***
     *
     * description 解锁
     *
     *
     * @return void
     * @author: woldier
     * @date: 2023/6/7 9:13
     */
    @Override
    public void unlock() {
        sync.release(0);
    }

    /***
     *
     * description 创建新的条件变量
     *
     *
     * @return java.util.concurrent.locks.Condition
     * @author: woldier
     * @date: 2023/6/7 9:13
     */
    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
    //-----------------------------------Lock interface implement  end--------------------------------------//

}
